import 'dart:math';
import 'dart:ui' as ui;
import 'dart:ui';

import 'package:flutter/material.dart';

import '../common/coordinate.dart';

class Paper extends StatefulWidget {
  const Paper({super.key});

  @override
  State<Paper> createState() => _PaperState();
}

class _PaperState extends State<Paper> with SingleTickerProviderStateMixin {
  late AnimationController _ctrl;

  @override
  void initState() {
    super.initState();
    _ctrl =
        AnimationController(vsync: this, duration: const Duration(seconds: 15))
          ..repeat();
  }

  @override
  void dispose() {
    _ctrl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: CustomPaint(
        painter: PaperPainter(_ctrl),
      ),
    );
  }
}

class PaperPainter extends CustomPainter {
  final Animation<double> repaint;

  PaperPainter(this.repaint) : super(repaint: repaint) {
    initPointsWithPolar();
  }

  final Paint mPaint = Paint()
    ..style = PaintingStyle.stroke
    ..strokeWidth = 2
    ..color = Colors.orange;
  final Path mPath = Path();
  final CoordinateByPath coordinate = CoordinateByPath();

  final List<Offset> points = [];
  final double step = 1;
  final double min = 0;
  final double max = 360;

  var colors = const [
    Color(0xFFF60C0C),
    Color(0xFFF3B913),
    Color(0xFFE7F716),
    Color(0xFF3DF30B),
    Color(0xFF0DF6EF),
    Color(0xFF0829FB),
    Color(0xFFB709F4),
  ];
  var pos = [1.0 / 7, 2.0 / 7, 3.0 / 7, 4.0 / 7, 5.0 / 7, 6.0 / 7, 1.0];

  void initPoints() {
    for (double x = -240; x <= 240; x += step) {
      points.add(Offset(x, f(x)));
    }
  }

  void initPointsWithPolar() {
    for (double x = min; x <= max; x += step) {
      double thta = (pi / 180 * x); // 角度转化为弧度
      //var p = 10 * thta;
      //var p = 100*(1-cos(thta));
      //var p = 150 * sin(5 * thta);
      var p =
          50 * (pow(e, cos(thta)) - 2 * cos(4 * thta) + pow(sin(thta / 12), 5));
      points.add(Offset(p * cos(thta), p * sin(thta)));
    }
  }

  double f(double x) {
    double y = -x * x / 200 + 100;
    return y;
  }

  @override
  void paint(Canvas canvas, Size size) {
    coordinate.paint(canvas, size);
    // 原点坐标移动到屏幕中心
    canvas.translate(size.width / 2, size.height / 2);

    //testDrawCurveLine(canvas);
    //testDrawPathLine(canvas);
    testDrawPathLineAnim(canvas);
  }

  /// 使用点线绘制函数曲线
  void testDrawCurveLine(Canvas canvas) {
    //initPoints();
    //initPointsWithPolar();

    mPaint.shader = ui.Gradient.linear(
        const Offset(0, 0), const Offset(100, 0), colors, pos, TileMode.mirror);

    canvas.drawPoints(PointMode.polygon, points, mPaint);
  }

  void testDrawPathLine(Canvas canvas) {
    //initPoints();
    //initPointsWithPolar();

    mPaint.shader = ui.Gradient.linear(
        const Offset(0, 0), const Offset(100, 0), colors, pos, TileMode.mirror);

    Offset p1 = points[0];
    Path path = Path()..moveTo(p1.dx, p1.dy);

    for (var i = 1; i < points.length - 1; i++) {
      double xc = (points[i].dx + points[i + 1].dx) / 2;
      double yc = (points[i].dy + points[i + 1].dy) / 2;
      Offset p2 = points[i];
      path.quadraticBezierTo(p2.dx, p2.dy, xc, yc);
    }
    canvas.drawPath(path, mPaint);

    PathMetrics pms = path.computeMetrics();
    for (var pm in pms) {
      Tangent? tangent = pm.getTangentForOffset(pm.length * repaint.value);
      if (tangent != null) {
        canvas.drawCircle(tangent.position, 5, mPaint..color = Colors.blue);
      }
    }
  }

  void testDrawPathLineAnim(Canvas canvas) {
    mPaint.shader = ui.Gradient.linear(
        const Offset(0, 0), const Offset(100, 0), colors, pos, TileMode.mirror);

    Offset p1 = points[0];
    Path path = Path()..moveTo(p1.dx, p1.dy);

    for (var i = 1; i < points.length - 1; i++) {
      double xc = (points[i].dx + points[i + 1].dx) / 2;
      double yc = (points[i].dy + points[i + 1].dy) / 2;
      Offset p2 = points[i];
      path.quadraticBezierTo(p2.dx, p2.dy, xc, yc);
    }

    PathMetrics pms = path.computeMetrics();
    for (var pm in pms) {
      // 提取路径绘制
      Tangent? tangent = pm.getTangentForOffset(pm.length * repaint.value);
      if (tangent != null) {
        canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), mPaint);
        canvas.drawCircle(tangent.position, 5, mPaint..color = Colors.blue);
      }
    }
  }

  @override
  bool shouldRepaint(covariant PaperPainter oldDelegate) =>
      oldDelegate.repaint != repaint;
}
